﻿/**
 * @file		dd_pmc_spi.h
 * @brief		SPI(Serial Peripheral Interface) driver
 * @note		None
 * @attention	None
 * 
 * <B><I>Copyright 2016 Socionext Inc.</I></B>
 */

/** @weakgroup dd_pmc_spi_overview
@{
	CM0 PMC - SPI Driver.<br>
	<br>
	The number of channels is 1 (ch0).
@}*//* --- end of dd_pmc_spi_overview */

/** @weakgroup dd_pmc_spi_sequence
@{
	- @ref dd_pmc_spi_sequence_sect
	- @ref dd_pmc_spi_dma_sequence_sect
	- @ref SPI_Sample_Send_Recv
	- @ref SPI_Sample_Full_Duplex
	- @ref SPI_Sample_DMA_Util_Send_Recv
	- @ref SPI_Sample_DMA_Util_Full_Duplex
	@section dd_pmc_spi_sequence_sect		Sequence example of SPI communication.
	@image html dd_pmc_spi.png
	@section dd_pmc_spi_dma_sequence_sect	Sequence example of SPI communication (DMA).
	@image html dd_pmc_spi_dma.png
	@section SPI_Sample_Send_Recv Sample of Send and Receive communication
	@code
	INT32			ret = D_DDIM_OK;
	UCHAR			send_buf[10] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x00,0x11};
	UCHAR			receive_buf[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	UINT32			send_size = 10;
	UINT32			receive_size = 10;
	ULONG			baudrate = 100000000;	// 100 Mbps;
	UCHAR			clk_div;
	INT32			index;
	T_DD_PMC_SPI_CTRL	spi_ctrl;

	ret = Dd_PMC_SPI_Calculate( baudrate, &clk_div );
	if( ret != D_DDIM_OK ) {
		Ddim_Print(("SPI Open ERR. ret=0x%x\n", ret));
		return ;
	}

	spi_ctrl.type				= E_DD_PMC_SPI_TYPE_MASTER;				// Master
	spi_ctrl.mode				= E_DD_PMC_SPI_MODE_2_CPOL1_CPHA0;		// Mode2:Clock Polarity=1, Clock Phase=0
	spi_ctrl.enable_sig			= E_DD_PMC_SPI_ENABLE_SIG_CPU;			// CPU. (software)
	spi_ctrl.bit_direction		= E_DD_PMC_SPI_BIT_DIR_MSB_FIRST;		// MSB first
	spi_ctrl.bit_length			= E_DD_PMC_SPI_BIT_LEN_8;				// 8 bit length
	spi_ctrl.clk_div			= clk_div;								// 100 Mbps
	spi_ctrl.delay_en			= 0;									// Disable delay (full speed)
	spi_ctrl.delay_val			= 0;									// Don't care
	spi_ctrl.rx_inhibit_en		= 0;									// Not inhibit
	spi_ctrl.fifo_depth			= 128;									// ch1 maximum size
	spi_ctrl.fifo_wmark_tx		= 64;									// Half of TX FIFO
	spi_ctrl.fifo_wmark_rx		= 64;									// Half of RX FIFO
	spi_ctrl.dma_en				= 0;									// DMA disable
	spi_ctrl.dma_recv_to		= 0;									// Don't care
	spi_ctrl.ss_info.cont_trans	= E_DD_PMC_SPI_CONT_TRANS_INACT_BETWEEN;// ssOut goes inactive between successive transfers
	spi_ctrl.ss_info.sspol[0]	= 1;									// Select Slave for TX/RX
	spi_ctrl.ss_info.sspol[1]	= 0;									// Do not select slave for TX/RX
	spi_ctrl.ss_info.sspol[2]	= 0;									// Do not select slave for TX/RX
	spi_ctrl.ss_info.sspol[3]	= 0;									// Do not select slave for TX/RX
	spi_ctrl.ss_info.ssout[0]	= 0;									// SSOUT is an active Low
	spi_ctrl.ss_info.ssout[1]	= 0;									// SSOUT is an active Low
	spi_ctrl.ss_info.ssout[2]	= 0;									// SSOUT is an active Low
	spi_ctrl.ss_info.ssout[3]	= 0;									// SSOUT is an active Low
	spi_ctrl.pcallback_ss		= 0;									// Disable callback

	ret = Dd_PMC_SPI_Ctrl( &spi_ctrl );

	// Transfer process
	ret = Dd_PMC_SPI_Set_Send_Data( send_buf, send_size );
	ret = Dd_PMC_SPI_Start_Send( (VP_PMC_SPI_CALLBACK)sample_callback_function );

	Ddim_Print(("SPI Send Complete. ret=0x%x\n", ret));

	// Receive process
	ret = Dd_PMC_SPI_Set_Recv_Data( receive_buf, receive_size );
	ret = Dd_PMC_SPI_Start_Recv( (VP_PMC_SPI_CALLBACK)sample_recv_callback_function );

	Ddim_Print(("SPI Receive Complete. ret=0x%x\n", ret));

	for( index = 0; index < receive_size; index++ ){
		Ddim_Print(("receive_buf[%d]=0x%02X\n", index, receive_buf[index]));
	}
	@endcode
	<br>
	<br>
	@section SPI_Sample_Full_Duplex Sample of Full-duplex communication
	@code
	// Sample Global Data
	static UCHAR	g_send_buf[10] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x00,0x11};
	static UCHAR	g_receive_buf[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	static UINT32	g_fullduplex_size = 10;

	// Sample Send Callback Function
	static VOID sample_send_callback_function( UINT32 result )
	{
		Ddim_Print(("SPI Send Callback : %x\n", result));
	}
	// Sample Receive Callback Function
	static VOID sample_recv_callback_function( UINT32 result )
	{
		INT32 index;

		Ddim_Print(("SPI Receive Callback : %x\n", result));
		for( index = 0; index < g_fullduplex_size; index++ ){
			Ddim_Print(("g_receive_buf[%d]=0x%02X\n", index, g_receive_buf[index]));
		}
	}
	@endcode
	<br>
	<br>
	@code
	INT32			ret = D_DDIM_OK;
	UCHAR			send_buf[10] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x00,0x11};
	UCHAR			receive_buf[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	UINT32			send_size = 10;
	UINT32			receive_size = 10;
	ULONG			baudrate = 100000000;	// 100 Mbps;
	UCHAR			clk_div;
	T_DD_PMC_SPI_CTRL	spi_ctrl;

	ret = Dd_PMC_SPI_Calculate( baudrate, &clk_div );
	if( ret != D_DDIM_OK ) {
		Ddim_Print(("SPI Open ERR. ret=0x%x\n", ret));
		return ;
	}

	spi_ctrl.type				= E_DD_PMC_SPI_TYPE_MASTER;				// Master
	spi_ctrl.mode				= E_DD_PMC_SPI_MODE_2_CPOL1_CPHA0;		// Mode2:Clock Polarity=1, Clock Phase=0
	spi_ctrl.enable_sig			= E_DD_PMC_SPI_ENABLE_SIG_CPU;			// CPU. (software)
	spi_ctrl.bit_direction		= E_DD_PMC_SPI_BIT_DIR_MSB_FIRST;		// MSB first
	spi_ctrl.bit_length			= E_DD_PMC_SPI_BIT_LEN_8;				// 8 bit length
	spi_ctrl.clk_div			= clk_div;							// 100 Mbps
	spi_ctrl.delay_en			= 0;								// Disable delay (full speed)
	spi_ctrl.delay_val			= 0;								// Don't care
	spi_ctrl.rx_inhibit_en		= 0;								// Not inhibit
	spi_ctrl.fifo_depth			= 128;								// ch1 maximum size
	spi_ctrl.fifo_wmark_tx		= 64;								// Half of TX FIFO
	spi_ctrl.fifo_wmark_rx		= 64;								// Half of RX FIFO
	spi_ctrl.dma_en				= 0;								// DMA disable
	spi_ctrl.dma_recv_to		= 0;								// Don't care
	spi_ctrl.ss_info.cont_trans	= E_DD_PMC_SPI_CONT_TRANS_INACT_BETWEEN;// ssOut goes inactive between successive transfers
	spi_ctrl.ss_info.sspol[0]	= 1;								// Select Slave for TX/RX
	spi_ctrl.ss_info.sspol[1]	= 0;								// Do not select slave for TX/RX
	spi_ctrl.ss_info.sspol[2]	= 0;								// Do not select slave for TX/RX
	spi_ctrl.ss_info.sspol[3]	= 0;								// Do not select slave for TX/RX
	spi_ctrl.ss_info.ssout[0]	= 0;								// SSOUT is an active Low
	spi_ctrl.ss_info.ssout[1]	= 0;								// SSOUT is an active Low
	spi_ctrl.ss_info.ssout[2]	= 0;								// SSOUT is an active Low
	spi_ctrl.ss_info.ssout[3]	= 0;								// SSOUT is an active Low
	spi_ctrl.pcallback_ss		= 0;								// Disable callback

	ret = Dd_PMC_SPI_Ctrl( &spi_ctrl );

	// Transfer set
	ret = Dd_PMC_SPI_Set_Send_Data( g_send_buf, g_fullduplex_size );

	// Receive set
	ret = Dd_PMC_SPI_Set_Recv_Data( g_receive_buf, g_fullduplex_size );

	//
	// Demand the preparation to the slave side device according to the handshaking signal.
	// And the waited for preparation completion. 
	//

	// Start communication
	ret = Dd_PMC_SPI_Start_Full_Duplex( (VP_PMC_SPI_CALLBACK)sample_send_callback_function, (VP_PMC_SPI_CALLBACK)sample_recv_callback_function );

	//
	// Communication completion is notified to the callback function.
	//
	@endcode
	<br>
	<br>
	@section SPI_Sample_DMA_Util_Send_Recv Sample of Send and Receive by DMA utility
	@code
	INT32			ret = D_DDIM_OK;
	UCHAR			dma_ch_send = 3;		// HDMAC ch for send:3
	UCHAR			dma_ch_recv = 4;		// HDMAC ch for recv:4
	UCHAR			send_buf[10] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x00,0x11};
	UCHAR			receive_buf[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	UINT32			send_size = 10;
	UINT32			receive_size = 10;
	ULONG			baudrate = 100000000;	// 100 Mbps;
	UCHAR			clk_div;
	INT32			index;
	T_DD_PMC_SPI_CTRL	spi_ctrl;

	ret = Dd_PMC_SPI_Calculate( baudrate, &clk_div );
	if( ret != D_DDIM_OK ) {
		Ddim_Print(("SPI Open ERR. ret=0x%x\n", ret));
		return ;
	}

	spi_ctrl.type				= E_DD_PMC_SPI_TYPE_MASTER;				// Master
	spi_ctrl.mode				= E_DD_PMC_SPI_MODE_2_CPOL1_CPHA0;		// Mode2:Clock Polarity=1, Clock Phase=0
	spi_ctrl.enable_sig			= E_DD_PMC_SPI_ENABLE_SIG_CPU;			// CPU. (software)
	spi_ctrl.bit_direction		= E_DD_PMC_SPI_BIT_DIR_MSB_FIRST;		// MSB first
	spi_ctrl.bit_length			= E_DD_PMC_SPI_BIT_LEN_8;				// 8 bit length
	spi_ctrl.clk_div			= clk_div;								// 100 Mbps
	spi_ctrl.delay_en			= 0;									// Disable delay (full speed)
	spi_ctrl.delay_val			= 0;									// Don't care
	spi_ctrl.rx_inhibit_en		= 0;									// Not inhibit
	spi_ctrl.fifo_depth			= 128;									// ch1 maximum size
	spi_ctrl.fifo_wmark_tx		= 64;									// Half of TX FIFO
	spi_ctrl.fifo_wmark_rx		= 64;									// Half of RX FIFO
	spi_ctrl.dma_en				= 1;									// DMA disable
	spi_ctrl.dma_recv_to		= 0x00800000;							// 8388609 clock count
	spi_ctrl.ss_info.cont_trans	= E_DD_PMC_SPI_CONT_TRANS_INACT_BETWEEN;// ssOut goes inactive between successive transfers
	spi_ctrl.ss_info.sspol		= 1;									// Select Slave for TX/RX
	spi_ctrl.ss_info.ssout		= 0;									// SSOUT is an active Low
	spi_ctrl.pcallback_ss		= 0;									// Disable callback

	ret = Dd_PMC_SPI_Ctrl( &spi_ctrl );

	// Transfer process
	ret = Dd_PMC_SPI_Set_Send_Data( send_buf, send_size );
	ret = Dd_PMC_SPI_Start_Send_DMA( dma_ch_send, (VP_PMC_SPI_CALLBACK)sample_send_callback_function );

	Ddim_Print(("SPI Send Complete. ret=0x%x\n", ret));

	// Receive process
	ret = Dd_PMC_SPI_Set_Recv_Data( receive_buf, receive_size );
	ret = Dd_PMC_SPI_Start_Recv_DMA( dma_ch_recv, (VP_PMC_SPI_CALLBACK)sample_recv_callback_function );

	for( index = 0; index < receive_size; index++ ){
		Ddim_Print(("receive_buf[%d]=0x%02X\n", index, receive_buf[index]));
	}

	Ddim_Print(("SPI Receive Complete. ret=0x%x\n", ret));
	@endcode
	<br>
	<br>
	@section SPI_Sample_DMA_Util_Full_Duplex Sample of Full-duplex by DMA utility
	@code
	INT32			ret = D_DDIM_OK;
	UCHAR			dma_ch_send = 3;		// HDMAC ch for send:3
	UCHAR			dma_ch_recv = 4;		// HDMAC ch for recv:4
	ULONG			baudrate = 100000000; 	// 100 Mbps;
	UCHAR			clk_div;
	T_DD_PMC_SPI_CTRL	spi_ctrl;

	ret = Dd_PMC_SPI_Calculate( baudrate, &clk_div );
	if( ret != D_DDIM_OK ) {
		Ddim_Print(("SPI Open ERR. ret=0x%x\n", ret));
		return ;
	}

	spi_ctrl.type				= E_DD_PMC_SPI_TYPE_MASTER;				// Master
	spi_ctrl.mode				= E_DD_PMC_SPI_MODE_2_CPOL1_CPHA0;		// Mode2:Clock Polarity=1, Clock Phase=0
	spi_ctrl.enable_sig			= E_DD_PMC_SPI_ENABLE_SIG_CPU;			// CPU. (software)
	spi_ctrl.bit_direction		= E_DD_PMC_SPI_BIT_DIR_MSB_FIRST;		// MSB first
	spi_ctrl.bit_length			= E_DD_PMC_SPI_BIT_LEN_8;				// 8 bit length
	spi_ctrl.clk_div			= clk_div;								// 100 Mbps
	spi_ctrl.delay_en			= 0;									// Disable delay (full speed)
	spi_ctrl.delay_val			= 0;									// Don't care
	spi_ctrl.rx_inhibit_en		= 0;									// Not inhibit
	spi_ctrl.fifo_depth			= 128;									// ch1 maximum size
	spi_ctrl.fifo_wmark_tx		= 64;									// Half of TX FIFO
	spi_ctrl.fifo_wmark_rx		= 64;									// Half of RX FIFO
	spi_ctrl.dma_en				= 1;									// DMA disable
	spi_ctrl.dma_recv_to		= 0x00800000;							// 8388609 clock count
	spi_ctrl.ss_info.cont_trans	= E_DD_PMC_SPI_CONT_TRANS_INACT_BETWEEN;// ssOut goes inactive between successive transfers
	spi_ctrl.ss_info.sspol		= 1;									// Select Slave for TX/RX
	spi_ctrl.ss_info.ssout		= 0;									// SSOUT is an active Low
	spi_ctrl.pcallback_ss		= 0;									// Disable callback

	ret = Dd_PMC_SPI_Ctrl( &spi_ctrl );

	// Transfer set
	ret = Dd_PMC_SPI_Set_Send_Data( g_send_buf, g_fullduplex_size );

	// Receive set
	ret = Dd_PMC_SPI_Set_Recv_Data( g_receive_buf, g_fullduplex_size );

	//
	// Demand the preparation to the slave side device according to the handshaking signal.
	// And the waited for preparation completion. 
	//

	// Start communication
	ret = Dd_PMC_SPI_Start_Full_Duplex_DMA( dma_ch_send, dma_ch_recv, (VP_PMC_SPI_CALLBACK)sample_send_callback_function, (VP_PMC_SPI_CALLBACK)sample_recv_callback_function );

	//
	// Communication completion is notified to the callback function.
	//
	@endcode

@}*//* --- end of dd_pmc_spi_sequence */

#ifndef _DD_PMC_SPI_H_
#define _DD_PMC_SPI_H_

/** @weakgroup dd_pmc_spi_definition
@{*/

#include "driver_common.h"

/*----------------------------------------------------------------------*/
/* Definition															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Return values
#define D_DD_PMC_SPI_NORMAL_COMPLETE		(D_DDIM_OK)									/**< SPI normal complete. */
#define D_DD_PMC_SPI_INPUT_PARAM_ERROR		(D_DD_PMC_SPI | D_DDIM_INPUT_PARAM_ERROR)	/**< Input parameter error. */
#define D_DD_PMC_SPI_STATUS_ABNORMAL		(D_DD_PMC_SPI | D_DDIM_STATUS_ABNORMAL)		/**< Abnormal Status */
#define D_DD_PMC_SPI_RECV_OVERRUN_ERROR		(D_DD_PMC_SPI | D_DDIM_OVERRUN_DATA)		/**< SPI receive overrun error. */
#define D_DD_PMC_SPI_DMA_SS_ERROR			(D_DD_PMC_SPI | D_DDIM_STATUS_ABNORMAL)		/**< SPI DMA stop status error. */
#define D_DD_PMC_SPI_TIMEOUT				(D_DD_PMC_SPI | D_DDIM_TIMEOUT)				/**< SPI Time Out(Only when the master) */
#define D_DD_PMC_SPI_FORCE_STOP				(D_DD_PMC_SPI | D_DDIM_FORCE_STOP)			/**< SPI Forced stop by Dd_PMC_SPI_Stop() */

/**
Type is defined to Callback function pointer when complete communication.<br>
@param [in] status		Complete status. (Same API return values)
*/
typedef VOID (*VP_PMC_SPI_CALLBACK)( UINT32 status );

/**
Type is defined to Callback function pointer when ssOut/ssIn is active.<br>
*/
typedef VOID (*VP_PMC_SPI_SS_CALLBACK)( VOID );


#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/*----------------------------------------------------------------------*/
/* Enumeration															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/** Transmit mode selection. */
typedef enum{
	E_DD_PMC_SPI_MODE_0_CPOL0_CPHA0 = 0,	/**< Mode0:Clock Polarity=0, Clock Phase=0<br>
											 Data are captured on the clock's rising edge and data is output on a falling edge. */
	E_DD_PMC_SPI_MODE_1_CPOL0_CPHA1,		/**< Mode1:Clock Polarity=0, Clock Phase=1
											 Data are captured on the clock's falling edge and data is output on a rising edge. */
	E_DD_PMC_SPI_MODE_2_CPOL1_CPHA0,		/**< Mode2:Clock Polarity=1, Clock Phase=0
											 Data are captured on clock's falling edge and data is output on a rising edge. */
	E_DD_PMC_SPI_MODE_3_CPOL1_CPHA1,		/**< Mode3:Clock Polarity=1, Clock Phase=1
											 Data are captured on clock's rising edge and data is output on a falling edge. */
} E_DD_PMC_SPI_MODE;

/** Master/Slave selection. */
typedef enum{
	E_DD_PMC_SPI_TYPE_SLAVE = 0,	/**< Type of Slave */
	E_DD_PMC_SPI_TYPE_MASTER		/**< Type of Master */
} E_DD_PMC_SPI_TYPE;

/** Data length selection. */
typedef enum{
	E_DD_PMC_SPI_BIT_LEN_4 = 3,		/**< 4 bit length */
	E_DD_PMC_SPI_BIT_LEN_5,			/**< 5 bit length */
	E_DD_PMC_SPI_BIT_LEN_6,			/**< 6 bit length */
	E_DD_PMC_SPI_BIT_LEN_7,			/**< 7 bit length */
	E_DD_PMC_SPI_BIT_LEN_8,			/**< 8 bit length */
	E_DD_PMC_SPI_BIT_LEN_9,			/**< 9 bit length */
	E_DD_PMC_SPI_BIT_LEN_10,		/**< 10 bit length */
	E_DD_PMC_SPI_BIT_LEN_11,		/**< 11 bit length */
	E_DD_PMC_SPI_BIT_LEN_12,		/**< 12 bit length */
	E_DD_PMC_SPI_BIT_LEN_13,		/**< 13 bit length */
	E_DD_PMC_SPI_BIT_LEN_14,		/**< 14 bit length */
	E_DD_PMC_SPI_BIT_LEN_15,		/**< 15 bit length */
	E_DD_PMC_SPI_BIT_LEN_16,		/**< 16 bit length */
} E_DD_PMC_SPI_BIT_LEN;

/** Bit direction selection. */
typedef enum {
	E_DD_PMC_SPI_BIT_DIR_LSB_FIRST = 0,	/**< LSB first */
	E_DD_PMC_SPI_BIT_DIR_MSB_FIRST		/**< MSB first */
} E_DD_PMC_SPI_BIT_DIR;

/** Enable signal selection. */
typedef enum{
	E_DD_PMC_SPI_ENABLE_SIG_CPU = 0,	/**< Use CPU. (software) */
	E_DD_PMC_SPI_ENABLE_SIG_EXT_0,		/**< use external enable 0. */
	E_DD_PMC_SPI_ENABLE_SIG_EXT_1,		/**< use external enable 1. */
	E_DD_PMC_SPI_ENABLE_SIG_EXT_2,		/**< use external enable 2. */
} E_DD_PMC_SPI_ENABLE_SIG;

/** ssOut continuous selection. */
typedef enum {
	E_DD_PMC_SPI_CONT_TRANS_INACT_BETWEEN = 0,	/**< ssOut goes inactive between successive transfers. */
	E_DD_PMC_SPI_CONT_TRANS_INACT_FIFO_EMPTY,	/**< ssOut become inactive when the TX FIFO is empty. */
	E_DD_PMC_SPI_CONT_TRANS_ACT_FIFO_EMPTY		/**< ssOut remain active even when the TX FIFO is empty. */
} E_DD_PMC_SPI_CONT_TRANS;


#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special

#endif

/*----------------------------------------------------------------------*/
/* Structure															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/** Slave Select setting information. */
typedef struct{
	E_DD_PMC_SPI_CONT_TRANS		cont_trans;		/**< Continuous Transfer enable. See @ref E_DD_PMC_SPI_CONT_TRANS.	*/
	UCHAR						ssout;			/**< Slave Select Output selection.<br>
														0: Do not select slave for TX/RX<br>
														1: Select Slave for TX/RX								*/
	UCHAR						sspol;			/**< Slave Select Polarity selection.<br>
														sspol = 0  : SSOUT/SSIN is an active Low<br>
														sspol = 1  : SSOUT/SSIN is an active High				*/
} T_DD_PMC_SPI_SS_INFO;

/** SPI control data. */
typedef struct {
	E_DD_PMC_SPI_TYPE			type;			/**< Master/Slave selection. */
	E_DD_PMC_SPI_MODE			mode;			/**< Transmit mode. See @ref E_DD_PMC_SPI_MODE. */
	E_DD_PMC_SPI_ENABLE_SIG		enable_sig;		/**< Enable signal selection. See @ref E_DD_PMC_SPI_ENABLE_SIG. */
	E_DD_PMC_SPI_BIT_DIR		bit_direction;	/**< Bit direction, LSB first or MSB first. */
	E_DD_PMC_SPI_BIT_LEN		bit_length;		/**< Data length. See @ref E_DD_PMC_SPI_BIT_LEN. */
	UCHAR						clk_div;		/**< Serial Clock Divisor.<br>
													 SCLK(bps) = extSclkM(SPICLK) / (2 * (clk_div + 1) */
	UCHAR						delay_en;		/**< Inter-Transfer Delay enable. (Master operation only)<br>
														0: Disable delay (full speed)<br>
														1: Enable delay. See @ref delay_val. */
	UCHAR						delay_val;		/**< SCLK cycles for Inter-transfer delay. (Master operation only)<br>
													 The delay is (mwait+1) SCLK cycles. */
	UCHAR						rx_inhibit_en;	/**< Inhibit the RX_FIFO.<br>
														0: Not inhibit<br>
														1: Inhibit the SPI bus from writing to the RX FIFO */
	UCHAR						fifo_depth;		/**< TX/RX FIFO depth. */
	UCHAR						fifo_wmark_tx;	/**< TX FIFO Watermark value. */
	UCHAR						fifo_wmark_rx;	/**< RX FIFO Watermark value. */
	UCHAR						dma_en;			/**< DMA enable.<br>
													 @remarks If set to 1, please use the Dd_PMC_SPI_Start_Xxxx_DMA() as the starting API. */
	UINT32						dma_recv_to;	/**< DMA Receive Timeout. (0 to 16,777,215)<br>
												 If the receive FIFO remains less than the RX watermark level for dma_recv_to(+1) HCLK cycles,
												 the DMA logic will issue a dma interrupt request to the CPU. */
	T_DD_PMC_SPI_SS_INFO		ss_info;		/**< Slave Select setting information. See @ref T_DD_PMC_SPI_SS_INFO */
	VP_PMC_SPI_SS_CALLBACK		pcallback_ss;	/**< Enable callback when the ssOut/ssIn is active. */
} T_DD_PMC_SPI_CTRL;


#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special

//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/*----------------------------------------------------------------------*/
/* Global Data															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/* Nothing Special */

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/*----------------------------------------------------------------------*/
/* Macro																*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/* Nothing Special */

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
// Nothing Special
//---------------------------- colabo section ----------------------------
// Nothing Special
#endif

/* @} */	// dd_pmc_spi_definition group

/** @weakgroup dd_pmc_spi_api
@{*/
/*----------------------------------------------------------------------*/
/* Function																*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
#ifdef __cplusplus
extern "C" {
#endif

/**
Set SPI operation condition and callback function for the specified channel.
@param [in]	spi_ctrl	SPI Control data. See @ref T_DD_PMC_SPI_CTRL.
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
@retval		D_DD_PMC_SPI_STATUS_ABNORMAL	: Abnormal status
@remarks
	- SPI format is supported only Motorola SPI.<br>
### DELETE_ES3
	- If master clock is 100MHz,<br>
	then CRG11_CLK5=0 by Dd_PMC_CRG11_Set_CRDM5_DIVMODE(0) and the parameter spi_ctrl->clk_div=0.<br>
### DELETE_ES3
*/
extern INT32 Dd_PMC_SPI_Ctrl( T_DD_PMC_SPI_CTRL const* const spi_ctrl );

/**
Get SPI operation condition and callback function for the specified channel.
@param [out]	spi_ctrl	SPI Control data. See @ref T_DD_PMC_SPI_CTRL.
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
*/
extern INT32 Dd_PMC_SPI_Get_Ctrl( T_DD_PMC_SPI_CTRL* const spi_ctrl );

/**
Set sending data information.
Please input transmitted data Buffer pointer and size information.
@param [in]	send_addr	Send data address
@param [in]	num			Number of data
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
@remarks
	- The value must be guaranteed about the transmission data until the transmission processing is completed.<br>
	- Set "USHORT" pointer to send_addr when Data Length is "E_DD_PMC_SPI_BIT_LEN_9" or more.<br>
	- Set "UCHAR" pointer to send_addr when Data Length is "E_DD_PMC_SPI_BIT_LEN_8" or less.<br>
	- If after this API was called the Dd_PMC_SPI_Set_Recv_Data(), "num" will be overwritten.
*/
extern INT32 Dd_PMC_SPI_Set_Send_Data( VOID const* const send_addr, UINT32 num );

/**
Start sending data.
@param [in]	pcallback		Send Callback function pointer
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
@retval		D_DD_PMC_SPI_FORCE_STOP			: Forced stop by Dd_PMC_SPI_Stop()
@retval		D_DD_PMC_SPI_TIMEOUT			: SPI Time Out
*/
extern INT32 Dd_PMC_SPI_Start_Send( VP_PMC_SPI_CALLBACK pcallback );

/**
Set receiving data information.
@param [in]	recv_addr	Receive data address
@param [in]	num			Number of data
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
@remarks
	- Set "USHORT" pointer to recv_addr when Data Length is "E_DD_PMC_SPI_BIT_LEN_9" or more. <br>
	- Set "UCHAR" pointer to recv_addr when Data Length is "E_DD_PMC_SPI_BIT_LEN_8" or less.<br>
	- If after this API was called the Dd_PMC_SPI_Set_Send_Data(), "num" will be overwritten.
*/
extern INT32 Dd_PMC_SPI_Set_Recv_Data( VOID const* const recv_addr, UINT32 num );

/**
Start receiving data.
@param [in]	pcallback		Receive Callback function pointer
@retval		D_DDIM_OK							: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR		: Input parameter error
@retval		D_DD_PMC_SPI_RECV_OVERRUN_ERROR		: Overrun error
@retval		D_DD_PMC_SPI_FORCE_STOP				: Forced stop by Dd_PMC_SPI_Stop()
*/
extern INT32 Dd_PMC_SPI_Start_Recv( VP_PMC_SPI_CALLBACK pcallback );

/**
Start full-duplex communication.
@param [in]	psend_callback	Send Callback function pointer
@param [in]	precv_callback	Receive Callback function pointer
@retval		D_DDIM_OK							: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR		: Input parameter error
*/
extern INT32 Dd_PMC_SPI_Start_Full_Duplex( VP_PMC_SPI_CALLBACK psend_callback, VP_PMC_SPI_CALLBACK precv_callback );

/**
Stop sending/receiving data(force stop).
@remarks
	- If want to run again after running this API, please reconfigure Dd_PMC_SPI_Ctrl().
*/
extern VOID Dd_PMC_SPI_Stop( VOID );

/**
Set SPI Slave Select setting.
@param [in]	ss_info		SPI Slave Select setting information. See @ref T_DD_PMC_SPI_SS_INFO.
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
*/
extern INT32 Dd_PMC_SPI_Set_Slave_Select( T_DD_PMC_SPI_SS_INFO const* const ss_info );

/**
Get SPI Slave Select setting.
@param [out]	ss_info	SPI Slave Select setting information. See @ref T_DD_PMC_SPI_SS_INFO.
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
*/
extern INT32 Dd_PMC_SPI_Get_Slave_Select( T_DD_PMC_SPI_SS_INFO* const ss_info );

/**
Set SPI clock divisor.
@param [in]		clk_div	Serial Clock Divisor.<br>
						SCLK = extSclkM(SPICLK) / (2 * (divisor + 1))
*/
extern VOID Dd_PMC_SPI_Set_Clock_Divisor( UCHAR clk_div );

/**
Get SPI clock divisor.
@param [out]	clk_div	Serial Clock Divisor.
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
*/
extern INT32 Dd_PMC_SPI_Get_Clock_Divisor( UCHAR* clk_div );

/**
Interrupt handler for SPI macro.<br>
*/
extern VOID Dd_PMC_SPI_Int_Handler( VOID );


#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------

/**
Calculate the clock divisor from the specified baudrate.
@param [in]		baudrate	baudrate (bps).
@param [out]	clk_div		clock divisor (result of calculate).
@retval		D_DDIM_OK					: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
*/
extern INT32 Dd_PMC_SPI_Calculate( ULONG baudrate, UCHAR* clk_div );

//---------------------------- colabo section ----------------------------
/**
Start sending data via DMA and SPI FIFO.
@param [in]	dma_ch		DMA channel number(0 to 7)
@param [in]	pcallback	Send Callback function pointer
@retval		D_DDIM_OK						: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR	: Input parameter error
@retval		D_DD_PMC_SPI_DMA_SS_ERROR		: DMA stop status error
@retval		D_DD_PMC_SPI_FORCE_STOP			: Forced stop by Dd_PMC_SPI_Stop()
@retval		D_DD_PMC_SPI_TIMEOUT			: SPI Time Out
*/
extern INT32 Dd_PMC_SPI_Start_Send_DMA( UCHAR dma_ch, VP_PMC_SPI_CALLBACK pcallback );

/**
Start receiving data via DMA and SPI FIFO.
@param [in]	dma_ch		DMA channel number(0 to 7)
@param [in]	pcallback	Receive Callback function pointer
@retval		D_DDIM_OK							: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR		: Input parameter error
@retval		D_DD_PMC_SPI_RECV_OVERRUN_ERROR		: Overrun error
@retval		D_DD_PMC_SPI_DMA_SS_ERROR			: DMA stop status error
*/
extern INT32 Dd_PMC_SPI_Start_Recv_DMA( UCHAR dma_ch, VP_PMC_SPI_CALLBACK pcallback );

/**
Start full duplex communication via DMA and SPI FIFO.
@param [in]	dma_ch_send		DMA channel number(for send)(0 to 7)
@param [in]	dma_ch_recv		DMA channel number(for recive)(0 to 7)
@param [in]	psend_callback	Send Callback function pointer
@param [in]	precv_callback	Receive Callback function pointer
@retval		D_DDIM_OK							: OK
@retval		D_DD_PMC_SPI_INPUT_PARAM_ERROR		: Input parameter error
 */
INT32 Dd_PMC_SPI_Start_Full_Duplex_DMA( UCHAR dma_ch_send, UCHAR dma_ch_recv, VP_PMC_SPI_CALLBACK psend_callback, VP_PMC_SPI_CALLBACK precv_callback );
#endif	// CO_DDIM_UTILITY_USE

#ifdef __cplusplus
}
#endif

/* @} */	// dd_pmc_spi_api group

#endif	// _DD_PMC_SPI_H_

